package concurrensy.producer_consumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.buffer.CircularFifoBuffer;

public class RingBufferWithLockAndCondition implements RingBuffer {

	private final Lock lock;
	private final Condition booferNotEmpty;
	private final Condition booferNotFool;
	private final Buffer buffer;

	public RingBufferWithLockAndCondition(int maxBufferSize) {
		buffer = new CircularFifoBuffer(maxBufferSize);
		lock = new ReentrantLock();
		booferNotEmpty = lock.newCondition();
		booferNotFool = lock.newCondition();
	}

	@Override
	public void addProduct(Object product) {
		lock.lock();
		try {
			CircularFifoBuffer buffer = (CircularFifoBuffer) this.buffer;
			if (buffer.size() == buffer.maxSize()) {
				try {
					booferNotFool.await();
					System.out.println("Producer waiting for product picking");
					return;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				buffer.add(product);
				System.out.println("Producer add product");
				booferNotEmpty.signal();
			}
		} finally {
			lock.unlock();
		}
	}

	@Override
	public void getProduct() {
		lock.lock();
		try {
			if (buffer.isEmpty()) {
				try {
					booferNotEmpty.await();
					System.out.println("Consumer waiting for product adding");
					return;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				buffer.remove();
				System.out.println("Consumer pick product");
				booferNotFool.signal();
			}
		} finally {
			lock.unlock();
		}
	}
}
